﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Algobox.Toolbox.Collections;
using System.ComponentModel;
using Algobox.Objects.Finance.Assets.Stock;
using Algobox.Feeds.Finance.MarketData;

namespace Algobox.Structure.Finance.Strategies.FractionPrototype
{
    public class FractionComponentDayMonitor : INotifyPropertyChanged, IMarketUpdateLast
    {
        public FractionComponentDayMonitor(
            FractionManagement manager,
            FractionComponentDay monitor)
        {
            Manager = manager;

            Manager.MarketFeed.SubscribeLast(monitor.Security, this);
            Manager.MarketFeed.SubscribeLast(monitor.SecurityPair, this);

            _monitor = monitor;

            LOG.Info("{0}|{1}:{2}|FractionComponentDayMonitor", monitor.Id, monitor.Security, monitor.SecurityPair);
        }

        public event PropertyChangedEventHandler PropertyChanged;
        
        private static readonly NLog.Logger LOG = NLog.LogManager.GetCurrentClassLogger();

        private FractionComponentDay _monitor;
        private bool _isEnabled;
        private double _midA;
        private double _midB;
        private double _moveDayA;
        private double _moveDayB;
        private double _diffDay;
        
        public FractionManagement Manager { get; set; }

        public bool IsLoaded { get; private set; }
        public bool IsStarted { get; private set; }

        public string SymbolA
        {
            get { return _monitor.Security.Symbol; }
            set
            {
                Manager.MarketFeed.UnsubscribeLast(_monitor.Security, this);
                _monitor.SymbolA = value;
                Manager.MarketFeed.SubscribeLast(_monitor.Security, this);
                NotifyPropertyChanged("SymbolA");
            }
        }
        public string SymbolB
        {
            get { return _monitor.SecurityPair.Symbol; }
            set
            {
                Manager.MarketFeed.UnsubscribeLast(_monitor.SecurityPair, this);
                _monitor.SymbolB = value;
                Manager.MarketFeed.SubscribeLast(_monitor.SecurityPair, this);
                NotifyPropertyChanged("SymbolB");
            }
        }
        public double CloseA
        {
            get { return _monitor.Security.Prices.OHLC.Close; }
            set { _monitor.Security.Prices.OHLC.Close = value; NotifyPropertyChanged("CloseA"); }
        }
        public double CloseB
        {
            get { return _monitor.SecurityPair.Prices.OHLC.Close; }
            set { _monitor.SecurityPair.Prices.OHLC.Close = value; NotifyPropertyChanged("CloseB"); }
        }
        public string TimeA
        {
            get { return _monitor.Security.Prices.Last.TimeStamp.ToLongTimeString(); }
        }
        public string TimeB
        {
            get { return _monitor.SecurityPair.Prices.Last.TimeStamp.ToLongTimeString(); }
        }
        public double LastA
        {
            get { return _monitor.Security.Prices.Last.Price; }
        }
        public double LastB
        {
            get { return _monitor.SecurityPair.Prices.Last.Price; }
        }
        public double MidA
        {
            get { return _midA; }
            set { _midA = value; NotifyPropertyChanged("MidA"); }
        }
        public double MidB
        {
            get { return _midB; }
            set { _midB = value; NotifyPropertyChanged("MidB"); }
        }
        public double DayMoveA
        {
            get { return _moveDayA * 100; }
            set { _moveDayA = value; NotifyPropertyChanged("DayMoveA"); }
        }
        public double DayMoveB
        {
            get { return _moveDayB * 100; }
            set { _moveDayB = value; NotifyPropertyChanged("DayMoveB"); }
        }
        public double DayDifference
        {
            get { return _diffDay * 100; }
            private set { _diffDay = value; NotifyPropertyChanged("DayDifference"); }
        }
        void  IMarketUpdateLast.OnPriceLast(IStock stock, Objects.Finance.Prices.PriceVolume last)
        {
            double mid;

            if (stock == _monitor.Security)
            {
                mid = (_monitor.Security.Prices.Ask.Price - _monitor.Security.Prices.Bid.Price) + _monitor.Security.Prices.Bid.Price;
                if (mid != _midA)
                {
                    MidA = mid;

                    DayMoveA = (mid - _monitor.Security.Prices.OHLC.Close) / _monitor.Security.Prices.OHLC.Close;
                    DayDifference = _moveDayA - _moveDayB;

                    if (CloseA == 0)
                    {
                        NotifyPropertyChanged("CloseA");
                    }
                }
                NotifyPropertyChanged("TimeA"); 
                NotifyPropertyChanged("LastA");
            }
            else if (stock == _monitor.SecurityPair)
            {
                mid = (_monitor.SecurityPair.Prices.Ask.Price - _monitor.SecurityPair.Prices.Bid.Price) + _monitor.SecurityPair.Prices.Bid.Price;
                if (mid != _midB)
                {
                    MidB = mid;

                    DayMoveB = (mid - _monitor.SecurityPair.Prices.OHLC.Close) / _monitor.SecurityPair.Prices.OHLC.Close;
                    DayDifference = _moveDayA - _moveDayB;

                    if (CloseB == 0)
                    {
                        NotifyPropertyChanged("CloseB");
                    }
                }
                NotifyPropertyChanged("TimeB");
                NotifyPropertyChanged("LastB");
            }
        }

        public void Unsubscribe()
        {
            Manager.MarketFeed.UnsubscribeLast(_monitor.Security, this);
            Manager.MarketFeed.UnsubscribeLast(_monitor.SecurityPair, this);
        }

        private void NotifyPropertyChanged(string propertyName)
        {
            if (PropertyChanged != null)
            {
                PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
            }
        }



    }
}
